﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Xyz.Web.Reservation.Models;
using Xyz.Web.Reservation.Repositories;

namespace Xyz.Web.Reservation.Controllers
{
    public class FlightController : Controller
    {
        FlightRepository flRep = new FlightRepository();
        SeatRepository sRep = new SeatRepository();

        public ActionResult Index()
        {
            SetViewData();
            return View();
        }

        public ActionResult ArrivalFlightStatus()
        {
            SetViewData();
            return View();
        }

        [HttpPost]
        public ActionResult ArrivalFlightStatus(FlightModel fModel)
        {
            if (ModelState.IsValid)
            {
                var flight = flRep.GetFlightStatus(fModel.FlightCode, fModel.ArrivalDateTime,fModel.ArrivalAirport,true);

                if (flight != null)
                {
                    SetViewData();
                    return View(flight.ToModel());
                }

                ModelState.AddModelError("", "No flight found");
            }

            SetViewData();
            return View();
        }

        public ActionResult DepartFlightStatus()
        {
            SetViewData();
            return View();
        }

        [HttpPost]
        public ActionResult DepartFlightStatus(FlightModel fModel)
        {
            if (ModelState.IsValid)
            {
                var flight = flRep.GetFlightStatus(fModel.FlightCode, fModel.DepartureDateTime, fModel.DepartureAirport,false);

                if (flight != null)
                {
                    SetViewData();
                    return View(flight.ToModel());
                }

                ModelState.AddModelError("", "No flight found");
            }

            SetViewData();
            return View();
        }

        private void SetViewData()
        { 
            List<AirportModel> AirModel  = flRep.GetAirports().ToModel();
            ViewData["AirportList"] = new SelectList(AirModel, "AirportCode","AirportName");
        }

        public ActionResult Search()
        {
            SetViewDataForSearch();
            return View();
        }

        [HttpPost]
        public ActionResult Search(FormCollection formValues)
        {                        
            string departureDate = Request.Form["DepartureDate"];
            string origin = Request.Form["Origin"];
            string destination = Request.Form["Destination"];
            string seatType = Request.Form["SeatType"];
            string pax = Request.Form["Pax"];
            string tripType = Request.Form["TripType"];
            string returnDate = null;
            if (tripType == "ReturnTrip")
            {
                returnDate = Request.Form["ReturnDate"];
            }

            if (origin == destination)
                ModelState.AddModelError("destination", "Departure and arrival airport must be different.");
            
            DateTime dtDepart, dtReturn;
            if (!DateTime.TryParse(departureDate, out dtDepart))
                ModelState.AddModelError("departureDate", "Invalid date.");
            else if (dtDepart < DateTime.Today)
                ModelState.AddModelError("departureDate", "Departure date must be from today onwards.");

            if (returnDate != null)
            {
                if (!DateTime.TryParse(returnDate, out dtReturn))
                    ModelState.AddModelError("returnDate", "Invalid date");
                else if (dtReturn < dtDepart)
                    ModelState.AddModelError("returnDate", "Return date must be later than departure date.");
            }

            if (ViewData.ModelState.IsValid)
            {
                Session["DepartureDate"] = departureDate;
                Session["Origin"] = origin;
                Session["Destination"] = destination;
                Session["SeatType"] = seatType;
                Session["Pax"] = pax;
                Session["TripType"] = tripType;
                Session["ReturnDate"] = returnDate;
                return RedirectToAction("Choose");
            }
            else
            {
                SetViewDataForSearch();
                ViewData["DepartureDate"] = departureDate;
                ViewData["Origin"] = origin;
                ViewData["Destination"] = destination;
                ViewData["SeatType"] = seatType;
                ViewData["Pax"] = pax;
                ViewData["TripType"] = tripType;
                ViewData["ReturnDate"] = returnDate;
                return View();
            }
            
            
        }

        private void SetViewDataForSearch()
        {
            SetViewData();

            // pax list
            List<SelectListItem> PaxList = new List<SelectListItem>(){
                new SelectListItem(){ Text = "1 Pax", Value = "1"},
                new SelectListItem(){ Text = "2 Pax", Value = "2"},
                new SelectListItem(){ Text = "3 Pax", Value = "3"},
                new SelectListItem(){ Text = "4 Pax", Value = "4"}
            };
            ViewData["PaxList"] = PaxList;

            // seat class list
            List<SelectListItem> SeatTypeList = new List<SelectListItem>(){
                new SelectListItem(){ Text = "Economy Class", Value = "EC"},
                new SelectListItem(){ Text = "Business Class", Value = "BC"},
                new SelectListItem(){ Text = "First Class", Value = "FC"}
            };
            ViewData["SeatTypeList"] = SeatTypeList;

            // trip type list
            List<SelectListItem> TripTypeList = new List<SelectListItem>(){
                new SelectListItem(){ Text = "One Way Trip", Value = "OneWayTrip"},
                new SelectListItem(){ Text = "Return Trip", Value = "ReturnTrip"}
            };
            ViewData["TripTypeList"] = TripTypeList;

        }

        public ActionResult Review()
        {
            TripListModel tripList = (TripListModel)Session["ChooseFlight"];
            int noOfPassenger = tripList.noOfPassenger;

            return View(tripList);
        }

        [HttpPost]
        public ActionResult Review(FormCollection collection)
        {
            TripListModel tripList = (TripListModel)Session["ChooseFlight"];
            int noOfPassenger = tripList.noOfPassenger;
            return RedirectToAction("Index", "Passenger", new { passengerCount = noOfPassenger } );
        }


        public ActionResult Choose(string FlightId, string TripType)
        {
            if (FlightId != null && TripType != null)
            {
                TripListModel tripList = (TripListModel)Session["ChooseFlight"];
                try
                {
                    int intFlightId = System.Convert.ToInt32(FlightId);
                    if (TripType == "Departures")
                    {
                        tripList.Trips[0].FlightId = intFlightId;
                    }
                    else
                    {
                        tripList.Trips[1].FlightId = intFlightId;
                    }
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError(string.Empty, ex.Message);
                }
                tripList.TotalTicketFare = GetTotalFare(tripList);
                Session["ChooseFlight"] = tripList;
                return View(tripList);
            }
            else
            {
                try
                {
                    List<DateTime> Dates = new List<DateTime>();

                    if (Session["DepartureDate"] == null || Session["DepartureDate"].ToString().Trim().Length == 0)
                    {
                        ModelState.AddModelError(string.Empty, "Please choose Depature Date.");
                        return View();
                    }
                    else
                    {
                        Dates.Add(DateTime.Parse(Session["DepartureDate"].ToString()));
                        if (Session["TripType"].ToString() == "ReturnTrip")
                        {
                            Dates.Add(DateTime.Parse(Session["ReturnDate"].ToString()));
                        }
                        string departureAirport = Session["Origin"].ToString();
                        string arrivalAirport = Session["Destination"].ToString();
                        string seatType = Session["SeatType"].ToString();
                        int noOfPassenger = System.Convert.ToInt32(Session["Pax"].ToString());

                        TripListModel tripList = new TripListModel();
                        tripList.departureAirport = departureAirport;
                        tripList.arrivalAirport = arrivalAirport;
                        tripList.seatType = seatType;
                        tripList.noOfPassenger = noOfPassenger;

                        Dates.Sort();
                        TripModel departureTrip = new TripModel();
                        departureTrip.TripType = "Departures";
                        departureTrip.TripDate = Dates[0];
                        List<FlightModel> departureFlights = Mapper.ToModel(flRep.GetFlights(departureTrip.TripDate, departureAirport, arrivalAirport));
                        List<ChooseFlightModel> departureChooseFlights = ToChooseFlightModel(departureFlights, tripList.seatType, tripList.noOfPassenger);
                        departureTrip.ChooseFlights = departureChooseFlights;
                        tripList.Trips.Add(departureTrip);
                        if (tripList.Trips[0].ChooseFlights.Count == 0)
                        {
                            ModelState.AddModelError(string.Empty, "There is no flight for Departures");
                        }

                        if (Dates.Count > 1)
                        {
                            TripModel returnTrip = new TripModel();
                            returnTrip.TripType = "Returns";
                            returnTrip.TripDate = Dates[1];
                            List<FlightModel> returnFlights = Mapper.ToModel(flRep.GetFlights(returnTrip.TripDate, arrivalAirport, departureAirport));
                            List<ChooseFlightModel> returnChooseFlights = ToChooseFlightModel(returnFlights, tripList.seatType, tripList.noOfPassenger);
                            returnTrip.ChooseFlights = returnChooseFlights;
                            tripList.Trips.Add(returnTrip);
                            if (tripList.Trips[1].ChooseFlights.Count == 0)
                            {
                                ModelState.AddModelError(string.Empty, "There is no flight for Returns");
                            }
                        }
                        tripList.TotalTicketFare = GetTotalFare(tripList);
                        Session["ChooseFlight"] = tripList;
                        return View(tripList);
                    }
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError(string.Empty, ex.Message);
                    return View();
                }
            }
        }

        private decimal GetTotalFare(TripListModel tripList)
        {
            decimal totalFare = 0;
            foreach (TripModel tm in tripList.Trips)
            {
                foreach (ChooseFlightModel cm in tm.ChooseFlights)
                {
                    if (cm.FlightId == tm.FlightId)
                    {
                        totalFare += cm.TotalFare;
                    }
                }
            }
            return totalFare;
        }

        private List<ChooseFlightModel> ToChooseFlightModel(List<FlightModel> Flights, string seatTypeCode, int noOfPassengers)
        {
            List<ChooseFlightModel> chooseFlights = new List<ChooseFlightModel>();
            foreach (FlightModel f in Flights)
            {
                var result = sRep.GetAvaliableAircraftSeatByFlightIdSeatTypeCode(f.FlightId, seatTypeCode);
                ChooseFlightModel c = new ChooseFlightModel();
                c.Available = (result.Count >= noOfPassengers);
                c.FlightId = f.FlightId;
                c.DepartureAirport = f.DepartureAirport;
                c.ArrivalAirport = f.ArrivalAirport;
                c.DepartureDateTime = f.DepartureDateTime;
                c.ArrivalDateTime = f.ArrivalDateTime;
                c.DepartureTerminal = f.DepartureTerminal;
                c.ArrivalTerminal = f.ArrivalTerminal;
                c.Distance = f.Distance;
                c.TaxSurcharge = f.TaxSurcharge;
                c.FlightStatus = f.FlightStatus;
                c.AircraftId = f.AircraftId;
                c.FlightCode = f.FlightCode;
                c.TotalFare = sRep.GetFlightPriceByFlightIdSeatTypeCode(f.FlightId, seatTypeCode) * noOfPassengers;
                c.TravelTime = f.ArrivalDateTime - f.DepartureDateTime;
                chooseFlights.Add(c);
            }
            return chooseFlights;
        }

        [HttpPost]
        public ActionResult Choose(string FlightId, string TripType, FormCollection collection)
        {
            TripListModel tripList = (TripListModel)Session["ChooseFlight"];
            List<FlightModel> fl = new List<FlightModel>();

            bool blnError = false;
            foreach (TripModel tm in tripList.Trips)
            {
                foreach (ChooseFlightModel cm in tm.ChooseFlights)
                {
                    if (cm.FlightId == tm.FlightId)
                    {
                        FlightModel f = new FlightModel();
                        f = Mapper.ToModel(flRep.GetFlightByFlightId(cm.FlightId));
                        fl.Add(f);
                    }
                }
                if (tm.ChooseFlights.Count == 0)
                {
                    ModelState.AddModelError(string.Empty, "There is no flight for " + tm.TripType);
                    blnError = true;
                }
                else if (tm.FlightId == 0)
                {
                    ModelState.AddModelError(string.Empty, "You must choose one flight from " + tm.TripType);
                    blnError = true;
                }
            }

            if (blnError)
            {
                return View(tripList);
            }
            else
            {
                Session["FlightsList"] = fl;
                return RedirectToAction("Review", "Flight");
            }
        }
        
    }
}